# 6.3 同步时序逻辑电路的设计 目标:根据逻辑功能要求,设计逻辑电路图。 1. 同步时序逻辑设计的一般步骤: ![image1](../../../../resources/25b5456018bd4dddac9441413b2f9bab.png) 2. 例:用D触发器设计一个8421BCD码同步十进制加计数器 分析:实质上是对时钟脉冲计数0, 1, 2, ..., 9, 0, 1, 2, ... 1. 列出状态表,分配状态 ![image2](../../../../resources/55821f631caa459daf73284a4d032bf7.png) 4位编码对应16种状态,本例只取其中10个为有效状态,其余为无效状态。 2. 选择触发器 每位Q对应一个D触发器,四位对应四个D触发器。特性方程: $Q^{n+1}=D$ 3. 确定方程组 $ Q_{3}^{n+1}=D_3=Q_{3}^{n}\overline{Q_{0}^{n}}+Q_{2}^{n}Q_{1}^{n}Q_{0}^{n} $ $ Q_{2}^{n+1}=D_2=Q_{2}^{n}\overline{Q_{1}^{n}}+Q_{2}^{n}\overline{Q_{0}^{n}}+\overline{Q_{2}^{n}}Q_{1}^{n}Q_{0}^{n} $ $ Q_{1}^{n+1}=D_1=Q_{1}^{n}\overline{Q_{0}^{n}}+\overline{Q_{3}^{n}Q_{1}^{n}}Q_{0}^{n} $, $ Q_{0}^{n+1}=D_0=\overline{Q_{0}^{n}} $ 4. 绘制逻辑电路图(略) 5. 检查自启动能力 将6个无效状态代入电路没有简化之前的方程组,求次态 ![image7](../../../../resources/9c058854b9f64d17adab2c218b9de1bc.png) 按照该方程组得到的电路具备自启动/自校正能力。 3. 例:设计一"011"序列检测器,每当X输入011码时,电路输出Y为1 ![image8](../../../../resources/582799407bf147e8b6107295d8c38418.png) 输入端X:串行随机信号 输出端Y:当X出现011序列时,Y=1;否则Y=0 1. 状态图的建立: ![image9](../../../../resources/9ece2dbb526b471faddb86c9b9746ef4.png) ![image10](../../../../resources/b90d7b8d2b9d41b19f293afb0ff06729.png) 状态A:开始检测/重新检测 状态B:表示已经收到了"0" 状态C:已经连续输入"01" 状态D:已经连续输入"011" 2. Verilog建模 1. 明确输入:时钟CP、被检信号X、复位rst 2. 输出:Y 3. 对状态进行编码 ```verilog module SequenceDetector011( input cp, input rst, input x, output y ); parameter STATE_A = 4'b0001; parameter STATE_B = 4'b0010; parameter STATE_C = 4'b0100; parameter STATE_D = 4'b1000; reg [3:0] state; always @(posedge cp or posedge rst) begin if (rst) begin state <= STATE_A; end else begin case (state) STATE_A: if (!x) state <= STATE_B; STATE_B: if (x) state <= STATE_C; STATE_C: if (x) state <= STATE_D; else state <= STATE_B; STATE_D: if (x) state <= STATE_A; else state <= STATE_B; default: state <= STATE_A; endcase end end assign y = (state == STATE_D); endmodule // SequenceDetector011 ``` 4. 有限状态机的设计 **时序逻辑电路就是和“状态”打交道**。状态机的本质就是对具有**逻辑顺序**或**时序规律**的事件的一种描述方法。状态机的工作方式是控制信号根据预先设定的状态“顺序”运行的,它是纯硬件系统中的**顺序控制电路**。通常采用case语句设计实现。 1. 根据功能要求,设计出状态图 明确状态的转换关系并注明状态转换条件注明输出与状态、输入的关系 2. 对状态进行编码 二进制编码、格雷编码、独热码 3. 分段设计状态机主体 1. 第一段:采用always模块描述状态转移条件和规律 2. 第二段:采用always或assign模块或组合逻辑描述输出 4. 检查是否有自启动能力 检查状态变量是否有初始值和默认值 1. always复位语句中赋初值 2. case分支语句中,要有default语句,将其它无效状态转到有效状态 5. 售货机设计 售货机能自动识别1元和0.5元的硬币,出货口和找零口,矿泉水的价格是1.5元。 已知关系:当投入的金额等于1.5元时,出货口输出一瓶矿泉水;当投入的金额大于1.5元时(即2元,不会超过2元),出货口输出一瓶矿泉水,同时找零口输出相应余额的硬币。 1. 明确输入输出: 输入:按键BTN、投币M(2bit,01表示0.5元,10表示1元) 隐性输入:clk、rst 输出:出水W、退钱:Y(2bit,01表示0.5元,10表示1元) 2. 画状态图 ![image11](../../../../resources/e20eadc570934c8884246f695f4cb84f.png) ![image12](../../../../resources/b617bb7ed330485598aa5d70cc35000b.png) ![image13](../../../../resources/03da107e9b6d440085e75f2ac31dc706.png) ![image14](../../../../resources/b8bda2b3face4b6d95913e3be9be80ef.png) 二进制编码: ```verilog parameter STATE_A = 4'b00; parameter STATE_B = 4'b01; parameter STATE_C = 4'b10; parameter STATE_D = 4'b11; ``` 独热码: ```verilog parameter STATE_A = 4'b0001; parameter STATE_B = 4'b0010; parameter STATE_C = 4'b0100; parameter STATE_D = 4'b1000; ``` ```verilog `default_nettype none module FiniteStateMachineSeller( clk, rst, inMoney, btnCancel, water, outMoney ); input wire clk; input wire rst; input wire [1:0] inMoney; // 01---$0.5, 10---$1.0 input wire btnCancel; // Out Money output wire water; // Out Water output wire [1:0] outMoney; // 01---$0.5, 10---$1.0 parameter ZERO = 7'b0000001; // Waiting... parameter HALF = 7'b0000010; // Get $0.5 parameter ONE = 7'b0000100; // Get $1.0 parameter ONE_AND_HALF = 7'b0001000; // Get $1.5 parameter TWO = 7'b0010000; // Get $2.0 parameter OUT_HALF = 7'b0100000; // Out $0.5 parameter OUT_ONE = 7'b1000000; // Out $1.0 reg [6:0] state; always @(posedge clk) begin if (rst) begin state <= ZERO; end else begin case (state) ZERO: if (inMoney == 2'b01) state <= HALF; else if (inMoney == 2'b10) state <= ONE; HALF: if (inMoney == 2'b01) state <= ONE; else if (inMoney == 2'b10) state <= ONE_AND_HALF; else if (btnCancel) state <= OUT_HALF; ONE: if (inMoney == 2'b01) state <= ONE_AND_HALF; else if (inMoney == 2'b10) state <= TWO; else if (btnCancel) state <= OUT_ONE; ONE_AND_HALF: state <= ZERO; TWO: state <= OUT_HALF; OUT_HALF: state <= ZERO; OUT_ONE: state <= ZERO; default: state <= ZERO; endcase end end assign water = (state == TWO) | (state == ONE_AND_HALF); assign outMoney = (state == OUT_ONE) ? 2'b10 : (state == OUT_HALF) ? 2'b01 : 2'b00; endmodule // FiniteStateMachineSeller ```